

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <signal.h>
#include <syslog.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <sys/reboot.h>


#include "iotv30_config.h"
#include "plcgw_cfg.h"
#include "print_log.h"
#include "sys_msg_process.h"
#include "ota_manager.h"

#include "print_log.h"
#include "plcgw_sys.h"
#include "uart_printf.h"



/*********************************************************/

int mode;
int sys_mode;

static key_t key_send_sysmsg;
static int msqid_send_sysmsg = -1;


/********************************************************************/

static int system_main_init(int clear_flag)
{
	if(!clear_flag) {
		key_send_sysmsg = ftok (MSG_QUEUE_PATH, MSG_ID_SYS_PUSH);
		if (key_send_sysmsg == -1) {
			perror ("ftok");
			return -1;
		}
	}
	else {
		if(msqid_send_sysmsg != -1) {
			if (msgctl(msqid_send_sysmsg, IPC_RMID, NULL) == -1) {
				perror("msgctl");
				return 1;
			}
		}
	}
	

	msqid_send_sysmsg = msgget (key_send_sysmsg,0644|IPC_CREAT ) ;
	if (msqid_send_sysmsg == -1) {
		perror ("msggetout");
		return -1;
	}

	// 删除现有的消息队列
    if (msgctl(msqid_send_sysmsg, IPC_RMID, NULL) == -1) {
        perror("msgctl");
        return 1;
    }

    // 重新创建新的消息队列
    msqid_send_sysmsg = msgget (key_send_sysmsg,0644|IPC_CREAT ) ;
	if (msqid_send_sysmsg == -1) {
		perror ("msggetout");
		return -1;
	}

	return 0;
}


void set_sys_mode(int mode)
{
	sys_mode = mode;	
	//show_led_by_mode();
}

int is_normal_mode(void)
{
	return (mode==MODE_NORMAL);
}
unsigned int get_mode(void)
{
	return mode;
}
void set_mode(unsigned int new_mode)
{
	mode = new_mode;
}




static void sigpipe_BC()
{
}





void start_ota()
{
	//log_notice("start ota........\n");
	logout("start ota........\n");
}

void system_reset()
{

	LOG_NAME();
	
#ifdef ESP32

#else
	log_notice("exit and reboot !.........\n");
  #if 0
	//exit(0);
	system("reboot");
  #else
	sync(); // 同步磁盘数据，将缓存数据回写到硬盘，以防数据丢失（必须）
	reboot(RB_AUTOBOOT);
  #endif	
#endif
}



void app_exit(int c)
{
	//stop_beep();
	exit(c);
}





static void sysmsg_queue_rcv_pro(void)
{
	int cnt = 0;
	while(1) {
		msgbuf_t msgbuf;
	
		ssize_t msgsz = msgrcv (msqid_send_sysmsg, &msgbuf,
			sizeof (msgbuf.mtext) - sizeof (msgbuf.mtext[0]), MSG_TYPE,
			MSG_NOERROR/* | IPC_NOWAIT*/);
		if (msgsz == -1) {
			if (errno == EIDRM) {
				log_debug ("msg queue(0x%08x/%d) has been killed\n", key_send_sysmsg, msqid_send_sysmsg);
				break;
			}
			else if (errno == ENOMSG) {
				log_debug ("no msg now...\n");
				sleep (1);
			}
			else {
				perror ("msgrcv");
				printf("sysmsg queue thread\n");
				//return -1;
				break;
			}
		}
		else {
			const sys_main_msg_t *pmsg = (sys_main_msg_t *)msgbuf.mtext;
			switch (pmsg->msg_type) {
#if 0
				case	EVT_EXEC_BIND:
					//exec_bind_queue_pro();
					break;
				case	MSG_REPORT_GW_STATUS:
					report_gw_status_from_msgq(pmsg);
					break;
				case	MSG_REPORT_ATTRS:
					report_device_attrs_msg(pmsg);
					break;

				case	EVT_FLUSH_LAMP_CCT: //MSG_FLUSH_LAMP_CCT_STATUS:
					flush_lamp_cct_status_pro();
					break;
				case	EVT_FLUSH_LAMP_RGB: // MSG_FLUSH_LAMP_RGB_STATUS:
					flush_lamp_rgb_status_pro();
					break;

				case	EVT_FLUSH_BK: // MSG_FLUSH_BK_STATUS:
					flush_bk_status_pro();  ////刷新断路器数据
					break;



#endif

				case	MSG_DOWNLOAD_OK:
					ota_burn_flash_pro(pmsg);
					break;

				case EVT_RESET_APP:
					printf("delay 2 sec , then reset app!\n");
					sleep(2);
					app_exit(0);
					break;
				case	EVT_RESET_SYSTEM:
					printf("delay 2 sec , then reset system!\n");
					sleep(2);
					system_reset();
					break;

				default:
					log_debug("unkown sys msg:%d", pmsg->msg_type);
					break;
			}
		}
	}
}

static void *sysmsg_queue_theard(void *param)
{
	pthread_detach(pthread_self()); 			 //设置该线程为分离状态，不需要主线程回收其系统资源。

	system_main_init(0);
	while(1) {
		sysmsg_queue_rcv_pro();  // 循环接收， 退出就是出错了！
		log_err("sysmsg_queue_rcv_pro   error exit! restart now\n");
		sleep(1);
		system_main_init(1);
	}

	printf("error exit .............. %s()\n", __FUNCTION__);
	
	pthread_exit(NULL);
	return NULL;
	
}

int plcgw_sysmsg_init(void)
{
	pthread_t tid_udp_rx;
	pthread_create(&tid_udp_rx, NULL, sysmsg_queue_theard, NULL);
	
	return 0;
}



int push_sysmsg_queue(const void *psrc, int len)
{
	if(msqid_send_sysmsg == -1) {
		return -1;
	}

	
	int msg_buf_len = len + sizeof(long);
	msgbuf_t *pbuf = (msgbuf_t *)malloc(msg_buf_len);
	if(pbuf == NULL) {
		perror("malloc of send_plc_msg_queue\n");
		return -1;
	}

	memcpy(pbuf->mtext, psrc, len);

	int ret = 0;
	pbuf->mtype = MSG_TYPE;
	ret = msgsnd (msqid_send_sysmsg, pbuf, len*sizeof (pbuf->mtext[0]), IPC_NOWAIT);
	if (ret == -1) {
		perror ("msgsnd");
		sys_main_msg_t *pt = (sys_main_msg_t*)psrc;
		printf("%s(), type=%d\n", __FUNCTION__, pt->msg_type);
	}

	free(pbuf);
	return ret;
}

void set_app_evt(int evt)
{
	unsigned char buf[8]={0};
	sys_main_msg_t *psys_msg = (sys_main_msg_t*)buf;
	psys_msg->msg_type = evt;
	push_sysmsg_queue(buf, 4);
			
}




